<?php
use Carbon\Carbon;

function noSecond($timeStr)
{
	return Carbon::parse($timeStr)->format("Y-m-d H:i");
}

function format($timeStr, $formatStr)
{
	return Carbon::parse($timeStr)->format($formatStr);
}

function now()
{
	return Carbon::now()->format("Y-m-d H:i");
}

function truncateText($txt, $len)
{
	if(mb_strlen($txt, "utf8") > $len){
		return mb_substr($txt, 0, $len) . "...";
	}
	return $txt;
}

//如果成功 返回OK
function setValue($key, $value)
{
	$val = Redis::set($key, $value);
	Redis::expire($key, env("REDIS_EXPIRE"));
	return $val;
}

//如果成功 返回值 否则返回0
function getValue($key)
{
	return Redis::get($key);
}

//如果成功 返回1 否则返回0
function deleteKey($key)
{
	return Redis::del($key);
}

//获取某个key的有效时间
function getTTL($key)
{
	return Redis::ttl($key);
}

//重置某个key的有效时间
function resetTTL($key)
{
	$val = getTTL($key);
	if($val < 0){
		Redis::expire($key, env("REDIS_EXPIRE"));
	}
}

//移除某个key的有效时间
function removeTTL($key)
{
	return Redis::persist($key);
}

//判断某个Key是否存在
function keyExists($key)
{
	return Redis::exists($key);
}

//获取某个key的数据类型
function keyType($key)
{
	return Redis::type($key);
}

//重命名某个Key，新名称必须是不存在的，成功返回1 失败返回0
function renameKey($key, $newkey)
{
	return Redis::renamenx($key, $newkey);
}

//设置一个时间戳为过期时间
function keyExpireAt($key, $unix)
{
	return Redis::expireat($key, $unix);
}

//查找所有匹配给定的模式的键 比如 *a* a?? dd_*
function patternKeys($pattern)
{
	return Redis::keys($pattern);
}

//在某个字符串后面追回，不需要设置过期时间
function appendStr($key, $string)
{
	return Redis::append($key, $string);
}

//从左边获取字符串某个部分
function stringRangeL($key, $start, $end)
{
	return Redis::getrange($key, $start, $end);
}

//从右边获取字符串某个部分 1为最右边第一个 2为最右边第二个
function stringRangeR($key, $start, $end)
{
	return Redis::getrange($key, -$start, -$end);
}

//获取字符串长度
function stringLength($key)
{
	return Redis::strlen($key);
}

/*
* List 操作
*/

//获取list长度，即使不存在该list，此处也返回0
function listLen($key)
{
	return Redis::llen($key);
}

//从右边开始删除count个值为value的元素
function listRemR($key, $count, $value)
{
	return Redis::lrem($key, -$count, $value);
}

//从左边开始删除count个值为value的元素
function listRemL($key, $count, $value)
{
	return Redis::lrem($key, $count, $value);
}

//删除全部值为value的元素
function listRemAll($key, $value)
{
	return Redis::lrem($key, 0, $value);
}

//在list右边推入一个元素，如果不存在该list，将会创建该list
function listPushR($key, $value)
{
	$exist = keyExists($key);
	$list = Redis::rpush($key, $value);
	if(!$exist)
	{
		resetTTL($key);
	}
	return $list;
}

//在list左边推入一个元素，如果不存在该list，将会创建该list
function listPushL($key, $value)
{
	$exist = keyExists($key);
	$list = Redis::lpush($key, $value);
	if(!$exist)
	{
		resetTTL($key);
	}
	return $list;
}

//从队列的左边出队一个元素，如果没有任何元素，返回空，否则返回出队的元素
function listPopL($key)
{
	return Redis::lpop($key);
}

//从队列的右边出队一个元素，如果没有任何元素，返回空，否则返回出队的元素
function listPopR($key)
{
	return Redis::rpop($key);
}

//修改索引为index的值为value
function listSet($key, $index, $value)
{
	return Redis::lset($key, $index, $value);
}

//从队列的右边入队一个元素，仅队列存在时有效, 如果成功则返回入队的值，否则返回0
function listPushRX($key, $value)
{
	return Redis::rpushx($key, $value);
}

//从队列的左边入队一个元素，仅队列存在时有效, 如果成功则返回入队的值，否则返回0
function listPushLX($key, $value)
{
	return Redis::lpushx($key, $value);
}

/*
* 左右trim的操作，当$start超过$end，即如果list长度为3, 而$start超过3，则list为被置空
* 如果$start未超过list的长度，而$end超过了，则$end会被当作list的最后一个元素，可以理解为从$start处开始，后面所有的元素
*/
//从左获取list中指定范围的元素，如果一个长度为4的list，ltrim(list, 0, 2)将返回0 1 2这三个元素的list
function listTrimL($key, $start, $end)
{
	return Redis::ltrim($key, $start, $end);
}

//从右获取list中指定范围的元素，如果一个长度为4的list，listTrimR(list, 1, 2)将返回最后两个，1表示最后一个 2表示最后第二个
function listTrimR($key, $start, $end)
{
	return Redis::ltrim($key, -$start, -$end);
}

//通过索引获取某个元素
function listIndex($key, $index)
{
	return Redis::lindex($key, $index);
}

//在列表中的另一个元素之前插入一个元素，如果$key指定的数据不是一个list，会返回一个error字符串; 如果$key指定的数据根本不存在，则返回一个0。
function listInsertB($key, $pivot, $value)
{
	try{
		$res = Redis::linsert($key, "BEFORE", $pivot, $value);
	}catch(\Predis\Response\ServerException $e){
		return "error";
	}
	return $res;
}

//在列表中的另一个元素之后插入一个元素，如果$key指定的数据不是一个list，会返回一个error字符串; 如果$key指定的数据根本不存在，则返回一个0。
function listInsertA($key, $pivot, $value)
{
	try{
		$res = Redis::linsert($key, "AFTER", $pivot, $value);
	}catch(\Predis\Response\ServerException $e){
		return "error";
	}
	return $res;
}

//从左边开始获取list指定范围的数据
function listRangeL($key, $start, $end)
{
	return Redis::lrange($key, $start, $end);
}

//从右边开始获取list指定范围的数据, 1表示最后一个，2表示最后第二个
function listRangeR($key, $start, $end)
{
	return Redis::lrange($key, -$start, -$end);
}

//获取整个列表
function listAll($key)
{
	return Redis::lrange($key, 0, -1);
}

//从source指定的list中，获取最后一个元素并移除，放入destination指定的list的最左边, 返回被操作的元素
function listPopRPushL($source, $destination)
{
	$exists = keyExists($destination);
	$value = Redis::rpoplpush($source, $destination);
	if(!$exists){
		resetTTL($destination);
	}
	return $value;
}

//list排序 desc 或 asc
function listSort($key, $type)
{
	return Redis::sort($key, "alpha", $type);
}

//list 排序并limit $type为desc 或 asc
function listSortLimit($key, $type, $start, $end)
{
	return Redis::sort($key, "alpha", $type, "limit", $start, $end);
}

//list 局部排序 $type为desc 或 asc
function listLocalSort($key, $local, $type)
{
	return Redis::sort($key, "by", $local, $type);
}

//list局部排序并limit $type为desc 或 asc
function listLocalLimitSort($key, $local, $type, $start, $end)
{
	return Redis::sort($key, "by", $local, "limit", $start, $end, $type);
}

/*
* Hash操作
*/

//设置一个键值对,如果不存在该hash 将创建
function setHashKV($key, $field, $value)
{
	$exists = keyExists($key);
	$hash = Redis::hset($key, $field, $value);
	if(!$exists){
		resetTTL($key);
	}
	return $hash;
}

//获取一个键的值
function getHashKV($key, $field)
{
	return Redis::hget($key, $field);
}

//是否存在
function existHashField($key, $field)
{
	return Redis::hexists($key, $field);
}

//获取所有字段
function getAllFields($key)
{
	return Redis::hkeys($key);
}

//获取所有值
function getAllValues($key)
{
	return Redis::hvals($key);
}

//读取所有字段跟值，变成list
function getAll($key)
{
	return Redis::hgetall($key);
}

//获取字段数量
function getFieldsNum($key)
{
	return Redis::hlen($key);
}

//设置一个字段，只有该字段不存在时才有效, 成功返回1 失败返回0
function setHashKVNX($key, $field, $value)
{
	return Redis::hsetnx($key, $field, $value);
}

/*
* Set操作
*/

// 添加成功到集合中，不存在则创建, 如果member已经存在 返回0 如果不存在 返回1
function addMember($set, $member)
{
	$exists = keyExists($set);
	$value = Redis::sadd($set, $member);
	if(!$exists){
		resetTTL($set);
	}
	return $value;
}

//获取两个集合的交集, 即如果first的members为 hello, second的members为 hello name, 此处返回的结果为hello
function getSetInter($first, $second)
{
	return Redis::sinter($first, $second);
}

//移动一个member到另一个集合中
function setMove($set, $destination, $memeber)
{
	$exists = keyExists($destination);
	$value = Redis::smove($set, $destination, $member);
	if(!$exists){
		resetTTL($destination);
	}
	return $value;
}

//获取set里的元素数量
function getSetNum($key)
{
	return Redis::scard($key);
}

//获取两个集合的交集，并保存至另一个结果集合中，如果结果集合存在，则被覆写
function setInterStore($set, $destination, $secondSet)
{
	$exists = keyExists($destination);
	$num = Redis::sinterstore($destination, $set, $secondSet);
	if(!$exists){
		resetTTL($destination);
	}
	return $num;
}

//随机获取一个元素，并删除
function setPop($key)
{
	return Redis::spop($key);
}

//合并多个集合
function setUnion($first, $second)
{
	return Redis::sunion($first, $second);
}

//获取set中不存在的元素
function setDiff($first, $second)
{
	return Redis::sdiff($first, $second);
}

//确定一个元素为一个集合的成员
function setIsMember($key, $member)
{
	return Redis::sismember($key, $member);
}

//随机获取一个元素, 如果count是整数且小于元素的个数，返回含有 count 个不同的元素的数组,如果count是个整数且大于集合中元素的个数时,仅返回整个集合的所有元素,当count是负数,则会返回一个包含count的绝对值的个数元素的数组，如果count的绝对值大于元素的个数,则返回的结果集里会出现一个元素出现多次的情况.
function setRandom($key, $count = 1)
{
	return Redis::srandmember($key, $count);
}

//合并集合并存到新的集合，如果新的集合已经存在，会被覆写
function setUnionStore($set, $destination, $secondSet)
{
	$exists = keyExists($destination);
	$value = Redis::sunionstore($destination, $set, $secondSet);
	if(!$exists){
		resetTTL($destination);
	}
	return $value;
}

//获取差集并保存至新的集合，如果新集合存在，会被覆写
function setDiffStore($set, $destination, $secondSet)
{
	$exists = keyExists($destination);
	$value = Redis::sdiffstore($destination, $set, $secondSet);
	if(!$exists){
		resetTTL($destination);
	}
	return $value;
}

//获取集合所有元素
function setMembers($key)
{
	return Redis::smembers($key);
}

//移除集合中的元素
function setRemoveMember($key, $member)
{
	return Redis::srem($key, $member);
}

/*
* 有序集合操作
*/

//添加元素到集合，如果存在，则更新分数，不存在则创建, score必须为整数或浮点数
function zAddMember($key, $score, $member)
{
	$exists = keyExists($key);
	$value = Redis::zadd($key, $score, $member);
	if(!$exists){
		resetTTL($key);
	}
	return $value;
}

//从左返回指定范围的元素, $type可以为withscores, 则返回一个数组，包括了分数
function zRangeMembersL($key, $start, $end, $type = "")
{
	return Redis::zrange($key, $start, $end, $type);
}

//从右返回指定范围的元素, $type可以为withscores, 则返回一个数组，包括了分数
function zRangeMembersR($key, $start, $end, $type = "")
{
	return Redis::zrange($key, -$start, -$end, $type);
}

//返回全部元素
function zRangeMembersAll($key, $type = "")
{
	return Redis::zrange($key, 0, -1, $type);
}

//返回给定分数范围内的所有元素, $min可以为 -inf， $max可以为+inf，在数字前加(，表示大于或小于该分类，不加(表示大于等于或小于等于
function zRangeByScore($key, $min, $max)
{
	return Redis::zrangebyscore($key, $min, $max);
}

//删除给定分数范围的元素
function zRemoveRangeByScore($key, $min, $max)
{
	return Redis::zremrangebyscore($key, $min, $max);
}

//获取某个成员的分数
function zMemberScore($key, $member)
{
	return Redis::zscore($key, $member);
}

//获取成员数量
function zMemberNum($key)
{
	return Redis::zcard($key);
}

//从左边开始，由高到低获取指定范围内的元素, type可以为withscores
function zRevertRangeL($key, $start, $end, $type = '')
{
	return Redis::zrevrange($key, $start, $end, $type);
}

//从右边开始
function zRevertRangeR($key, $start, $end, $type = '')
{
	return Redis::zrevrange($key, -$start, -$end, $type);
}

//获取全部从高到低
function zRevertRangeAll($key, $type = '')
{
	return Redis::zrevrange($key, 0, -1, $type);
}

//给定分数范围内的元素数量
function zMemberCount($key, $min, $max)
{
	return Redis::zcount($key, $min, $max);
}

//某个元素在集合中的索引
function zMemberRank($key, $member)
{
	return Redis::zrank($key, $member);
}

//删除一个成员
function zMemberRemove($key, $member)
{
	return Redis::zrem($key, $member);
}

//合并两个有序集合
function zUnionStore($destination, $first, $second)
{
	$exists = keyExists($destination);
	$value = Redis::zunionstore($destination, 2, $first, $second);
	if(!$exists){
		resetTTL($destination);
	}
	return $value;
}

//交集
function zInterStore($destination, $first, $second)
{
	$exists = keyExists($destination);
	$value = Redis::zinterstore($destination, 2, $first, $second);
	if(!$exists){
		resetTTL($destination);
	}
	return $value;
}

//从低分开始，删除指定排名的元素
function zRemoveRangeByRankL($key, $start, $end)
{
	return Redis::zremrangebyrank($key, $start, $end);
}

//从高分开始，删除指定排名的元素
function zRemoveRangeByRankH($key, $start, $end)
{
	return Redis::zremrangebyrank($key, -$start, -$end);
}